package com.example.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.jwt.JWT;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.common.ValidateCodeUtils;
import com.example.dto.LoginDto;
import com.example.dto.UserDto;
import com.example.exception.NullException;
import com.example.exception.ParamException;
import com.example.mapper.UserMapper;
import com.example.entity.User;
import com.example.service.UserService;
import com.example.thead.ThreadLocalUtil;
import com.example.vo.LoginVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import static com.example.constant.Constant.*;

/**
 * @author itheima
 */
@Service
@Slf4j
public class UserServiceImpl implements UserService {
    @Resource
    private UserMapper userMapper;
    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @Override
    public Boolean sendMsg(LoginDto loginDto) {
        if (ObjectUtil.isEmpty(loginDto) || StrUtil.isBlank(loginDto.getPhone())) {
            throw new ParamException("入参为空");
        }
        User user = new User();
        BeanUtils.copyProperties(loginDto, user);
        String code = ValidateCodeUtils.generateValidateCode(6).toString();
        log.info("验证码{}", code);
        //使用Redis存储验证码
        redisTemplate.opsForValue().set(USER_CODE + user.getPhone(), code, 60, TimeUnit.MINUTES);

        //发送短信(需要扣钱0.045)
        //SMSUtils.sendMessage(SIGN_NAME, TEMPLATE_CODE, user.getPhone(), code);
        return true;
    }

    @Override
    public LoginVo login(LoginDto loginDto) {
        if (ObjectUtil.isEmpty(loginDto) || StrUtil.isBlank(loginDto.getPhone()) || StrUtil.isBlank(loginDto.getCode())) {
            throw new ParamException("入参为空");
        }
        String code = redisTemplate.opsForValue().get(USER_CODE + loginDto.getPhone());
        if (ObjectUtil.isEmpty(code)) {
            throw new NullException("对象为空");
        }
        //判断验证码是否一致
        if (!code.equals(loginDto.getCode())) {
            return null;
        }

        User user = new User();
        BeanUtils.copyProperties(loginDto, user);

        //根据手机号从数据库中找到用户
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        lqw.eq(User::getPhone, user.getPhone());
        User userInfo = userMapper.selectOne(lqw);

        LoginVo loginVo = new LoginVo();
        Boolean firstLogin = false;

        //判断用户是否存在
        if (userInfo == null) {
            //不存在则新增用户
            userInfo = new User();
            userInfo.setPhone(user.getPhone());
            userInfo.setUsername("用户" + user.getPhone());
            userInfo.setGender(0);
            userInfo.setAvatar("");
            userInfo.setBirthday(null);
            userInfo.setCity("");
            int insert = userMapper.insert(userInfo);
            if (insert != 1) {
                throw new RuntimeException("新增用户失效");
            }
        }
        //判断用户信息是否填写完整，不完整则提醒前端需跳转信息填写页面
        if (userInfo.getGender() == 0 || StrUtil.isBlank(userInfo.getUsername())
                || userInfo.getBirthday() == null || StrUtil.isBlank(userInfo.getCity())) {
            firstLogin = true;
        }

        //成功以后，签token
        String token = JWT.create()
                //载荷不允许放敏感信息
                //载荷开始
                //推荐必选
                .setPayload(TOKEN_USER_ID, userInfo.getId())
                //可选
                .setPayload(TOKEN_USER_PHONE, userInfo.getPhone())
//                .setPayload("用户的头像", userInfo.getPhone())
                //可选
                .setPayload(TOKEN_USER_NAME, userInfo.getUsername())
                //载荷结束
                //key不要给出去
                .setKey(TOKEN_KEY.getBytes())
                .sign();

        loginVo.setToken(token);
        loginVo.setFirstLogin(firstLogin);
        return loginVo;
    }

    @Override
    public Boolean updateUser(UserDto userDto) {
        if (ObjectUtil.isEmpty(userDto)) {
            throw new ParamException("入参为空");
        }

        User user = new User();
        BeanUtils.copyProperties(userDto, user);

        User userLocal = (User) ThreadLocalUtil.get();
        if (userLocal.getId() == null) {
            throw new ParamException("全局变量用户id为空");
        }
        log.info("用户id{}", userLocal.getId());

        user.setId(userLocal.getId());
        user.setUpdateUser(userLocal.getId());
        user.setUpdateTime(LocalDateTime.now());
        int res = userMapper.updateById(user);
        return res == 1;
    }

    @Override
    public Boolean updatePhone(LoginDto loginDto) {
        if (ObjectUtil.isEmpty(loginDto) || StrUtil.isBlank(loginDto.getPhone()) || StrUtil.isBlank(loginDto.getCode())) {
            throw new ParamException("入参为空");
        }

        String code = redisTemplate.opsForValue().get(USER_CODE + loginDto.getPhone());
        if (ObjectUtil.isEmpty(code)) {
            throw new NullException("对象为空");
        }
        //判断验证码是否一致
        if (!code.equals(loginDto.getCode())) {
            return null;
        }

        User userLocal = (User) ThreadLocalUtil.get();
        if (userLocal.getId() == null) {
            throw new ParamException("全局变量用户id为空");
        }

        //根据id从数据库中找到用户
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        lqw.eq(User::getId, userLocal.getId());
        User userInfo = userMapper.selectOne(lqw);
        if (userInfo == null) {
            throw new NullException("该用户不存在");
        }

        //用户存在可以修改
        User user = new User();
        BeanUtils.copyProperties(loginDto, user);

        //2.判断新手机号在数据库是否存在
        //2.1存在，该用户则不能修改
        LambdaQueryWrapper<User> newLqw = new LambdaQueryWrapper<>();
        newLqw.eq(User::getPhone, user.getPhone());
        User userDb = userMapper.selectOne(newLqw);
        if (userDb != null) {
            return null;
        }

        //2.2不存在，该用户则可以修改
        user.setId(userLocal.getId());
        user.setUpdateUser(userLocal.getId());
        user.setUpdateTime(LocalDateTime.now());
        int res = userMapper.updateById(user);
        return res == 1;
    }

    @Override
    public Boolean checkCode(LoginDto loginDto) {
        if (ObjectUtil.isEmpty(loginDto) || StrUtil.isBlank(loginDto.getCode())) {
            throw new ParamException("入参为空");
        }
        User userLocal = (User) ThreadLocalUtil.get();
        if (userLocal.getId() == null) {
            throw new ParamException("全局变量用户id为空");
        }

        //根据id从数据库中找到用户
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        lqw.eq(User::getId, userLocal.getId());
        User userInfo = userMapper.selectOne(lqw);
        if (userInfo == null) {
            throw new NullException("该用户不存在");
        }

        String code = redisTemplate.opsForValue().get(USER_CODE + userInfo.getPhone());
        if (ObjectUtil.isEmpty(code)) {
            throw new NullException("对象为空");
        }
        //判断验证码是否一
        if (!code.equals(loginDto.getCode())) {
            return false;
        }
        return true;
    }

    @Override
    public List<User> getUsersByIds(List<String> userIds) {
        if (CollectionUtils.isEmpty(userIds)) {
            throw new RuntimeException("入参为空");
        }
        List<User> users = userMapper.selectBatchIds(userIds);
        if (Objects.isNull(users)) {
            return new ArrayList<>();
        }
        return users;
    }

}
